package com.nx.platform.es.biz.esspider.resource;

import com.google.common.base.Throwables;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.nx.arch.rdb.sharding.config.xml.api.XmlShardingDataSource;
import com.nx.arch.rdb.sharding.jdbc.ShardingDataSource;
import com.nx.platform.es.common.utils.MoreMaps;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * @author
 * @date 2018/01/25
 */
public class DBResource {

    private static final String DRIVER_CLASS = "driver-class";
    private static final String DRIVER_CLASS_DEFAULT_VALUE = "com.mysql.jdbc.Driver";
    private static final String JDBC_URL = "jdbc-url";
    private static final String USER = "user";
    private static final String PASSWORD = "password";
    private static final String INITIAL_POOL_SIZE = "initial-pool-size";
    private static final String ACQUIRE_INCREMENT = "acquire-increment";
    private static final String MIN_POOL_SIZE = "min-pool-size";
    private static final String MAX_POOL_SIZE = "max-pool-size";
    private static final String TYPE = "shard";

    private final String configFilePath;
    private final String id;
    private final Map<?, ?> settings;
    private NamedParameterJdbcTemplate jdbcTemplate;

    public DBResource(String configFilePath, String code, Map<?, ?> settings) {
        this.configFilePath = configFilePath;
        this.id = code;
        this.settings = settings;
    }

    public NamedParameterJdbcTemplate getJdbcTemplate() {
        if (jdbcTemplate != null) {
            return jdbcTemplate;
        }
        synchronized (this) {
            if (jdbcTemplate != null) {
                return jdbcTemplate;
            }
            InputStream is = null;
            try {
                boolean shard = MoreMaps.getBooleanValue(settings, TYPE);
                if (shard) {
                    File config = new File(configFilePath + "/" + id + ".xml");
                    is = new FileInputStream(config);
                    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    Document doc = db.parse(is);
                    XmlShardingDataSource x = new XmlShardingDataSource(doc);
                    jdbcTemplate = new NamedParameterJdbcTemplate(x);
                } else {
                    String driverClass = MoreMaps.getString(settings, DRIVER_CLASS, DRIVER_CLASS_DEFAULT_VALUE);
                    String jdbcUrl = MoreMaps.getString(settings, JDBC_URL);
                    String user = MoreMaps.getString(settings, USER);
                    String password = MoreMaps.getString(settings, PASSWORD);
                    int initialPoolSize = MoreMaps.getIntValue(settings, INITIAL_POOL_SIZE, 1);
                    int acquireIncrement = MoreMaps.getIntValue(settings, ACQUIRE_INCREMENT, 1);
                    int minPoolSize = MoreMaps.getIntValue(settings, MIN_POOL_SIZE, 1);
                    int maxPoolSize = MoreMaps.getIntValue(settings, MAX_POOL_SIZE, 2);
                    ComboPooledDataSource dataSource = new ComboPooledDataSource();
                    dataSource.setDriverClass(driverClass);
                    dataSource.setJdbcUrl(jdbcUrl);
                    dataSource.setUser(user);
                    dataSource.setPassword(password);
                    dataSource.setInitialPoolSize(initialPoolSize);
                    dataSource.setMinPoolSize(minPoolSize);
                    dataSource.setAcquireIncrement(acquireIncrement);
                    dataSource.setMaxPoolSize(maxPoolSize);
                    dataSource.setMaxIdleTime(25000);
                    dataSource.setCheckoutTimeout(30000);
                    dataSource.setTestConnectionOnCheckin(true);
                    dataSource.setTestConnectionOnCheckout(false);
                    dataSource.setIdleConnectionTestPeriod(600);
                    jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
                }
            } catch (Exception e) {
                Throwables.throwIfUnchecked(e);
                throw new RuntimeException(e);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return jdbcTemplate;
    }

    public void releaseJdbcTemplate() {
        if (jdbcTemplate != null) {
            JdbcTemplate template = (JdbcTemplate) jdbcTemplate.getJdbcOperations();
            if (template.getDataSource() instanceof ComboPooledDataSource) {
                ComboPooledDataSource dataSouce = (ComboPooledDataSource) template.getDataSource();
                dataSouce.close();
            }
            if (template.getDataSource() instanceof ShardingDataSource) {
                ShardingDataSource dataSouce = (ShardingDataSource) template.getDataSource();
                dataSouce.shutdown();
            }
        }
    }

    public String getId() {
        return id;
    }

}
